package GDoc::Job::Fetch::US::Legi::GPO;

use Moose;

use XML::LibXML;
use Scalar::Util 'blessed';
use File::Temp;

extends 'GDoc::Job::Fetch';

my $MODS_URL = 'http://www.loc.gov/mods/v3';


sub run { 
    my $self = shift;
    my %data = %{ $self->data };

    if ( $data{link} ) { 
        $self->_fetch_pdf;
    } elsif ( $data{index} ) { 
        $self->_fetch_index;
    } else { 
        $self->_setup_indexes;
    }
}


sub _setup_indexes { 
    my $self = shift;

    my $coms = $self->_committee_map;

    $self->logger->info( "Submitting index jobs for committees: " . join ', ', sort keys %$coms );

    foreach my $committee ( sort keys %$coms ) { 
        foreach my $congress ( 110 .. 114 ) { 
            my $index_url = sprintf( $self->_baseurl, $coms->{$committee}, $congress );

            my $class = blessed $self;
            $class =~ s/GDoc::Job:://;

            my $job = GDoc::Job->new( class => $class,
                                      queue => $self->fetch_queue,
                                      data  => { index      => $index_url,
                                                 committee  => $committee,
                                                 congress   => $congress
                                               }
                                    );
            $job->submit;
        }
    }
}


sub _fetch_index { 
    my $self = shift;
    my %data = %{ $self->data };

    $self->logger->info( "Fetching index for committee $data{committee}, congress $data{congress}" );

    my $mech = $self->_mech;
    $mech->get( $data{index} );

    my @more_links = $mech->find_all_links( text_regex => qr/More/, 
                                            url_regex  => qr/granuleId/ ); 

    my $class = blessed $self;
    $class =~ s/GDoc::Job:://;

    foreach my $link( @more_links ) { 
        my $job = GDoc::Job->new( class => $class,
                                  queue => $self->fetch_queue,
                                  data  => { link       => $self->_basedir . $link->url,
                                             committee  => $data{committee},
                                             congress   => $data{congress},
                                           }
                                );

        $job->submit;
    }      
}


sub _fetch_pdf { 
    my $self = shift;
    my %data = %{ $self->data };

    my $mech = $self->_mech;
    $mech->get( $data{link} );

    my $MODS_link = $mech->find_link( text_regex => qr/MODS/ );
    $mech->get( $MODS_link );
    my $xml = $mech->response->content;
    my $meta = $self->_parse_MODS( $xml );

    my $pdf_url = delete $meta->{pdf};

    my $ident    = $self->_ident( $meta, \%data );
    my $filename = $ident . '.pdf';
    my $key      = sprintf( $self->_basekey, $data{committee}, $filename );

    $self->logger->info( "Checking key $key" );

    if ( $self->_check_key( $key ) ) { 
        $self->logger->info( "Already have $pdf_url, skipping" );
        return;
    }

    $meta->{identifier} = $ident;
    $meta->{description} = $meta->{title};

    $self->logger->info( "Storing PDF $pdf_url --> $key" );

    # some of these are big so let's use a temp file
    my $tmpf = File::Temp->new;
    $mech->get( $pdf_url, ':content_file' => $tmpf->filename );
    
    $self->logger->info( "Wrote PDF to temp file " . $tmpf->filename );

    $self->store_pdf( key       => $key,
                      datafile  => $tmpf,
                      filename  => $filename,
                      meta      => $meta
                    );

    my $xml_filename = $ident . '.mods.xml';
    my $xml_key      = sprintf( $self->_basemeta, $data{committee}, $xml_filename );

    $self->logger->info( "Storing XML metadata --> $xml_key" );

    $self->store_xml( key      => $xml_key,
                      data     => $xml,
                      filename => $xml_filename
                    );

}


sub _parse_MODS { 
    my $self = shift;
    my $xml = shift;

    # I hate XML with the burning fire of ten billion suns
    my $parser = XML::LibXML->new;
    my $tree   = $parser->parse_string( $xml );

    # manually register a namespace for some stupid reason
    my $xc     = XML::LibXML::XPathContext->new( $tree );
    $xc->registerNs( 'mods', $MODS_URL );

    my %meta;

    # not all of these will be available in all MODS files
    $meta{sudoc}    = $xc->findnodes( q{//mods:classification[@authority='sudocs']} )->string_value;
    $meta{cite}     = $xc->findnodes( q{//mods:identifier[@type='preferred citation']} )->string_value;
    $meta{date}     = $xc->findnodes( q{//mods:dateIssued} )->string_value;
    $meta{title}    = $xc->findnodes( q{/mods:mods/mods:titleInfo/mods:title} )->string_value;
    $meta{calendar} = $xc->findnodes( q{//mods:congCalendar/@number} )->string_value;
    $meta{pdf}      = $xc->findnodes( q{//mods:url[@displayLabel='PDF rendition']} )->string_value;
    $meta{congress} = $xc->findnodes( q{//mods:congSerial/@congress} )->string_value;
    $meta{snum}     = $xc->findnodes( q{//mods:congSerial/@number} )->string_value;


    return \%meta;
}




1;
